C syntax
![]() C syntax is the form that text must have in order to be C programming language code. The language syntax rules are designed to allow for code that is terse, has a close relationship with the resulting object code, and yet provides relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development. C syntax makes use of the maximal munch principle. As a free-form language, C code can be formatted different ways without affecting its syntactic nature. C syntax influenced the syntax of succeeding languages, including C++, Java, and C#. High level structureC code consists of preprocessor directives, and core-language types, variables and functions; organized as one or more source files. Building the code typically involves preprocessing and then compiling each source file into an object file. Then, the object files are linked to create an executable image. Variables and functions can be declared separately from their definition. A declaration identifies the name of a user-defined element and some if not all of the information about how the element can be used at run-time. A definition is a complete description of an element that includes the declaration aspect as well as additional information that completes the element. For example, a function declaration indicates the name and optionally the type and number of arguments that it accepts. A function definition includes the same information (argument information is not optional), plus code that implements the function logic. Entry pointFor a hosted environment, a program starts at an entry point function named int main() {...}
int main(void) {...}
int main(int argc, char *argv[]) {...}
int main(int argc, char **argv) {...}
The first two definitions are equivalent; meaning that the function does not use the two arguments. The second two are also equivalent; allowing the function to access the two arguments. The return value, typed as A minimal program consists of a parameterless, empty int main(){}
Unlike other functions, the language[a] requires that a program act as if it returns 0 even if it does not end with a In a free-standing (non-hosted) environment, such as a system without an operating system, the standard allows for different startup handling. It need not require a Command-line argumentsArguments included in the command line to start a program are passed to a program as two values – the number of arguments (customarily named myFilt abc def
The following code prints the value of the command-line parameters. #include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc\t= %d\n", argc);
for (int i = 0; i < argc; i++)
printf("argv[%i]\t= %s\n", i, argv[i]);
}
Reserved keywordsThe following words are reserved – not allowed as identifiers:
The following keywords are often substituted for a macro or an appropriate keyword from the above list. Some of the following keywords are deprecated since C23.
Implementations may reserve other keywords, although implementations typically provide non-standard keywords that begin with one or two underscores. The following keywords are classified as extensions and conditionally-supported:
Preprocessor directivesThe following are directives to the preprocessor.
The CommentsA comment – informative text to a programmer that is ignored by a language translator – can be included in code either as the line or block comment syntax. A line comment starts with In some situations, comment markers are ignored. The text of a string literal is exempt from being considered a comment start. And, comments cannot be nested. For example, The line comment syntax, sometimes called C++ style originated in BCPL and became valid syntax in C99. It is not available in the original K&R version nor in ANSI C. The following code demonstrates comments. Line 1 contains a line comment and lines 3-4 contain a block comment. Line 4 demonstrates that a block comment can be embedded in a line with code both before and after it. int i; // line comment
/* block
comment */
int ii = /* always zero */ 0;
The following demonstrates a potential problem with the comment syntax. What is intended to be the divide operator x = *p/*q;
The following text is not valid C syntax since comments do not nest. It seems that lines 3-5 are a comment nested inside the comment block spanning lines 1-7. But, actually line 5 ends the comment started on line 1. This leaves line 6 to be interpreted as code which is clearly not valid C syntax. /*
First of comment block
/*
First line of what is intended to be an inner block
*/
Compiler treats this line as code but it's not valid!
*/
IdentifiersThe syntax supports user-defined identifiers. An identifier must start with a letter (A-Z, a-z) or an underscore (_), subsequent characters can be letters, numbers (0-9), or underscores and it must not be a reserved word. Identifiers are case sensitive; making Evaluation orderThere can be multiple ways to evaluation an expression consistent with the mathematical notation. For example, To reduce run-time issues with evaluation order yet afford some optimizations, the standard states that expressions may be evaluated in any order between sequence points which are defined as any of the following:
Expressions before a sequence point are always evaluated before those after a sequence point. In the case of short-circuit evaluation, the second expression may not be evaluated depending on the result of the first expression. For example, in the expression The arguments to a function call may be evaluated in any order, as long as they are all evaluated by the time the function is entered. The following expression, for example, has undefined behavior: printf("%s %s\n", argv[i = 0], argv[++i]);
Type systemPrimitive typesThe language supports primitive numeric types for integer and real values which typically map directly to the instruction set architecture of a central processing unit (CPU). Integer data types store values in a subset of integers, and real data types store values in a subset of real numbers in floating-point. A complex data type stores two real values. Integer types have Integer typesThe integer types come in different fixed sizes, capable of representing various ranges of numbers. The type The representation of some types may include unused "padding" bits, which occupy storage but are not included in the width. The following table lists the integer types using the shortest possible name and indicating the minimum width in bits.
The In general, the widths and representation scheme implemented for any given platform are chosen based on the machine architecture, with some consideration given to the ease of importing source code developed for other platforms. The width of the In addition to the standard integer types, there may be other "extended" integer types, which can be used for Integer constants may be specified in source code in several ways. Numeric values can be specified as decimal (example: Enumerated typeThe enumerated type, specified with the Some compilers warn if an object with enumerated type is assigned a value that is not one of its constants. However, such an object can be assigned any values in the range of their compatible type, and An enumerated type is declared with the enum colors { RED, GREEN, BLUE = 5, YELLOW } paint_color;
This declares the Floating-point typesA floating-point form is used to represent numbers with a fractional component. They do not, however, represent most rational numbers exactly; they are instead a close approximation. There are three standard types of real values, denoted by their specifiers (and since C23 three more decimal types): single precision (
Floating-point constants may be written in decimal notation, e.g. The standard header file C23 introduces three additional decimal (as opposed to binary) real floating-point types: _Decimal32, _Decimal64, and _Decimal128.
Despite that, the radix has historically been binary (base 2), meaning numbers like 1/2 or 1/4 are exact, but not 1/10, 1/100 or 1/3. With decimal floating point all the same numbers are exact plus numbers like 1/10 and 1/100, but still not e.g. 1/3. No known implementation does opt into the decimal radix for the previously known to be binary types. Since most computers do not even have the hardware for the decimal types, and those few that do (e.g. IBM mainframes since IBM System z10), can use the explicitly decimal types.
Storage classThe following table describes the specifiers that define various storage attributes including duration – static (default for global), automatic (default for local), or dynamic (allocated).[citation needed]
Variables declared within a block by default have automatic storage, as do those explicitly declared with the Objects with automatic storage are local to the block in which they were declared and are discarded when the block is exited. Additionally, objects declared with the The The Note that storage specifiers apply only to functions and objects; other things such as type and enum declarations are private to the compilation unit in which they appear.[citation needed] Types, on the other hand, have qualifiers (see below). Type qualifiersTypes can be qualified to indicate special properties of their data. The type qualifier Incomplete typesAn incomplete type is a structure or union type whose members have not yet been specified, an array type whose dimension has not yet been specified, or the They are often used with pointers, either as forward or external declarations. For instance, code could declare an incomplete type like this: struct thing *pt;
This declares An incomplete type can be completed later in the same scope by redeclaring it. For example: struct thing {
int num;
};
Incomplete types are used to implement recursive structures; the body of the type declaration may be deferred to later in the translation unit: typedef struct Bert Bert;
typedef struct Wilma Wilma;
struct Bert {
Wilma *wilma;
};
struct Wilma {
Bert *bert;
};
Incomplete types are also used for data hiding. The incomplete type is defined in a header file, and the full definition is hidden in a single body file. PointersIn a variable declaration, the asterisk ( A pointer value associates two pieces of information: a memory address and a data type. ReferencingWhen a non-static pointer is declared, it has an unspecified value. Dereferencing it without first assigning it, results in undefined behavior. The int a = 0;
int *ptr = &a;
DereferencingAn asterisk before a variable name (when not in a declaration or a mathematical expression) dereferences a pointer to allow access to the value it points to. In the following example, the integer variable b is set to the value of integer variable a, which is 10: int a=10;
int *p;
p = &a;
int b = *p;
ArraysArray definitionArrays store consecutive elements of the same type. The following code declares an array of 100 elements of type int. int array[100];
If declared outside of a function (globally), the size must be a constant value. If declared in a function, the array size may be a non-constant expression. The number of elements is available as Accessing elementsThe primary facility for accessing array elements is the array subscript operator. For example, Due to arrays and pointers being interchangeable, the address of each elements can be expressed in pointer arithmetic. The following table illustrates both methods for the existing the same array:
Since the expression Variable-length arraysC99 standardized the variable-length array (VLA) in block scope that produced an array sized by runtime information (not a constant value) but with fixed size until the end of the block.[1] As of C11, this feature is no longer required to be implemented by the compiler. int n = ...;
int a[n];
a[3] = 10;
Multidimensional arraysThe language supports arrays of multiple dimensions – stored in row-major order which is essentially a one-dimensional array with elements that are arrays. Given that ROWS and COLUMNS are constants, the following declares a two-dimensional array of length ROWS; each element of which is an array of COLUMNS integers. int array2d[ROWS][COLUMNS];
The following is an example of accessing an integer element: array2d[4][3]
Reading from left to right, this accesses the 5th row, and the 4th element in that row. The expression
Higher-dimensional arrays can be declared in a similar manner. A multidimensional array should not be confused with an array of pointers to arrays (also known as an Iliffe vector or sometimes an array of arrays). The former is always rectangular (all subarrays must be the same size), and occupies a contiguous region of memory. The latter is a one-dimensional array of pointers, each of which may point to the first element of a subarray in a different place in memory, and the sub-arrays do not have to be the same size. TextAlthough the language provides types for textual character data, neither the language nor the standard library defines a string type, but the null terminated string is commonly used. A string value is a contiguous series of characters with the end denoted by a zero value. The standard library contains many string handling functions for null-terminated strings, but string manipulation can and often is handled via custom code. String literalA string literal is code text surrounded by double quotes; for example The language supports string literal concatenation – adjacent string literals are treated as joined at compile time. This allows long strings to be split over multiple lines, and also allows string literals from preprocessor macros to be appended to strings at compile time. For example, the source code: printf(__FILE__ ": %d: Hello "
"world\n");
becomes the following after the preprocessor expands printf("helloworld.c" ": %d: Hello "
"world\n");
which is equivalent to: printf("helloworld.c: %d: Hello world\n");
Character constantsThe character literal, called character constant, is single-quoted, e.g. A character constant cannot be empty (i.e. Nevertheless, in situations limited to a specific platform and the compiler implementation, multicharacter constants do find their use in specifying signatures. One common use case is the OSType, where the combination of Classic Mac OS compilers and its inherent big-endianness means that bytes in the integer appear in the exact order of characters defined in the literal. The definition by popular "implementations" are in fact consistent: in GCC, Clang, and Visual C++, Like string literals, character constants can also be modified by prefixes, for example Backslash escapesControl characters cannot be included in a string or character literal directly. Instead they can be encoded via an escape sequence starting with a backslash ( Escape sequences include:
The use of other backslash escapes is not defined by the standard, although compilers often provide additional escape codes as language extensions. For example, the escape sequence Note that the standard library function printf() uses Wide character stringsSince type Wide characters are most commonly either 2 bytes (using a 2-byte encoding such as UTF-16) or 4 bytes (usually UTF-32), but Standard C does not specify the width for The original standard specified only minimal functions for operating with wide character strings; in 1995 the standard was modified to include much more extensive support, comparable to that for The now generally recommended method[note 3] of supporting international characters is through UTF-8, which is stored in Variable width stringsA common alternative to StructureA structure is a container consisting of a sequence of named members of heterogeneous types; similar to a record in other languages. The first field starts at the address of the structure and the members are stored in consecutive locations in memory, but the compiler can insert padding between or after members for efficiency or as padding required for proper alignment by the target architecture. The size of a structure includes padding. A structure is declared with the The following declares a structure named struct s {
int x;
float y;
char *z;
} tee;
Structure members cannot have an incomplete or function type. Thus members cannot be an instance of the structure being declared (because it is incomplete at that point) but a field can be a pointer to the type being declared. Once declared, a variable can be declared of the structure type.
The following declares a new instance of the structure struct s r;
Although some prefer to declare a struct variable using the typedef struct {int i;} s_type;
Accessing membersA member is accessed using dot notation. For example, given the declaration of tee from above, the member y can be accessed as A structure is commonly accessed via a pointer. Consider AssignmentAssigning a value to a member is like assigning a value to a variable. The only difference is that the lvalue (left side value) of the assignment is the name of the member; per above syntax. A structure can also be assigned as a whole to another structure of the same type; passed by copy as a function argument or return value. For example, Other operationsThe operations supported for a structure are: initialize, copy, get address and access a field. Of note, the language does not support comparing the value of two structures other than via custom code to compare each field. Bit fieldsThe language provides a special type of member known as a bit field, which is an integer with a specified size in bits. A bit field is declared as a member of type (signed/unsigned) Unnamed fields indicate padding and consist of just a colon followed by a number of bits. Specifying a width of zero for an unnamed field is used to force alignment to a new word.[7] Since all members of a union occupy the same memory, unnamed bit-fields of width zero do nothing in unions, however unnamed bit-fields of non zero width can change the size of the union since they have to fit in it. Bit fields are limited compared to normal fields in that the address-of ( The following declares a structure type named struct f {
unsigned int flag : 1;
signed int num : 4;
signed int : 3;
} g;
UnionFor the most part, a union is like a structure except that fields overlap in memory to allow storing values of different type although not at the same time. The union is like the variant record of other languages. Each field refers to the same location in memory. The size of a union is equal to the size of its largest component type plus any padding. A union is declared with the union u {
int x;
float y;
char *z;
} n;
InitializationScalarInitializing a variable along with declaring it involves appending an equals sign and then a construct that is compatible with the data type. The following initializes an int: int x = 12;
Because of the language's grammar, a scalar initializer may be enclosed in any number of curly brace pairs. Most compilers issue a warning if there is more than one such pair. The following are legal although arguably unusual: int y = { 23 };
int z = { { 34 } };
Initializer listStructures, unions and arrays can be initialized after a declaration via an initializer list. Since unmatched elements are set to 0, an empty list sets all elements to 0. For example, the following sets all elements of array a and all fields of s to 0: int a[10] = {};
struct s s = {};
If an array is declared without an explicit size, the array is an incomplete type. The number of initializers determines the size of the array and completes the type. For example: int x[] = { 0, 1, 2 };
By default, the items of an initializer list correspond with the elements in the order they are defined. Including too many values yields an error. The following statement initializes an instance of the structure s named pi: struct s {
int x;
float y;
char *z;
};
struct s pi = { 3, 3.1415, "Pi" };
Designated initializersDesignated initializers allow members to be initialized by name, in any order, and without explicitly providing preceding values. The following initialization is functionally equivalent to the previous: struct s pi = { .z = "Pi", .x = 3, .y = 3.1415 };
Using a designator in an initializer moves the initialization "cursor". In the example below, if int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };
In C89, a union was initialized with a single value applied to its first member. That is, the union u defined above could only have its x member initialized: union u value = { 3 };
Using a designated initializer, the member to be initialized does not have to be the first member: union u value = { .y = 3.1415 };
Compound designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood. In the example below, struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };
This is equivalent to: struct { int a[3], b; } w[] =
{
{ { 1, 0, 0 }, 0 },
{ { 2, 0, 0 }, 0 }
};
Compound literalsIt is possible to borrow the initialization methodology to generate compound structure and array literals: // pointer created from array literal.
int *ptr = (int[]){ 10, 20, 30, 40 };
// pointer to array.
float (*foo)[3] = &(float[]){ 0.5f, 1.f, -0.5f };
struct s pi = (struct s){ 3, 3.1415, "Pi" };
Compound literals are often combined with designated initializers to make the declaration more readable:[1] pi = (struct s){ .z = "Pi", .x = 3, .y = 3.1415 };
Function pointersA pointer to a function can be declared like: type-name (*function-name)(parameter-list); The following program code demonstrates the use of a function pointer for selecting between addition and subtraction. Line 5 defines a function pointer variable named int add(int x, int y) { return x + y; }
int subtract(int x, int y) { return x - y; }
int main(int argc, char* args[])
{
int (*operation)(int x, int y);
operation = argc ? add : subtract;
int result = operation(1, 1);
return result;
}
OperatorsThis is a list of operators in the C and C++ programming languages. All listed operators are in C++ and lacking indication otherwise, in C as well. Some tables include a "In C" column that indicates whether an operator is also in C. Note that C does not support operator overloading. When not overloaded, for the operators Most of the operators available in C and C++ are also available in other C-family languages such as C#, D, Java, Perl, and PHP with the same precedence, associativity, and semantics. Many operators specified by a sequence of symbols are commonly referred to by a name that consists of the name of each symbol. For example,+= and -= are often called "plus equal(s)" and "minus equal(s)", instead of the more verbose "assignment by addition" and "assignment by subtraction".LabelsA label marks a point in the code to which control can be transferred. A label is an identifier followed by a colon. For example: if (i == 1) goto END;
// other code
END:
The standard does not define a method to retrieve the address of a label, but
GCC extends the language with a unary For example, the following prints void *ptr = &&J1;
J1: printf("hi");
goto *ptr;
Control flowCompound statementA compound statement, a.k.a. statement block, is a matched pair of curly braces with any number of statements between, like: { {statement} } As a compound statement is a type of statement, when statement is used, it could be a single statement (without enclosing braces) or a compound statement (with enclosing braces). A compound statement is required for a function body and for a control structure branch that is not one statement. A variable declared in a block can be referenced by code in that block (and inner blocks) below the declaration. Access to memory used for a block-declared variable after the block close (i.e. via a pointer) results in undefined behavior. If statementThe if (expression) statement else statement If the expression is not zero, control passes to the fist statement. Otherwise, control passes to the second statement. If the Notably, the second statement can be another if (i == 1)
printf("it's 1");
else if (i == 2)
printf("it's 2");
else
printf("it's something else");
Switch statementThe switch(expression) { case label-name: statement case label-name: statement . . . default: statement } Each Execution continues from one It is possible, although unusual, to locate Iteration statementThere are three forms of iteration statement: while (expression) statement do statement while (expression) for (init; test; next) statement For the The logic of for (e1; e2; e3)
s;
is equivalent to: e1;
while (e2)
{
s;
cont:
e3;
}
except for the behavior of a Any of the three expressions in the Since C99, the first expression may take the form of a declaration with scope limited to the sub-statement For example: for (int i = 0; i < limit; ++i) {
// ...
}
Jump statementThere are four jump statements (transfer control unconditionally): The goto label-name A while (1)
{
// ...
continue;
}
do
{
// ...
continue;
} while (1);
for (; ; ) {
// ...
continue;
}
The The FunctionsDefinitionFor a function that returns a value, a definition consists of a return type name, a function name that is unique in the codebase, a list of parameters in parentheses, and a statement block that ends with a type-name function-name(parameter-list) { statement-list return value; } A function that returns no value is declared with void function-name(parameter-list) { statement-list } The standard does not include lamba functions, but some translators do. ParametersA parameter-list is a comma-separated list of formal parameter declarations; each item a type name followed by a variable name: type-name variable-name{, type-name variable-name} The return type cannot be an array or a function. For exmaple: int f()[3]; // Error: function returning an array
int (*g())[3]; // OK: function returning a pointer to an array
void h()(); // Error: function returning a function
void (*k())(); // OK: function returning a function pointer
If the function accepts no parameters, the parameter-list may be the keyword A function can accept a variable number of arguments by including int printf(const char *, ...);
Consuming variable length arguments can be accomplished via standard library functions declared in CallingCode can access a function of a library if it is both declared and defined. Often a declaration is provided for a library function via a header file that the consuming code uses via the Accessing a user-defined function that is defined in a different file is similar to using a library function. The consuming code declares the function either by including a header file or directly in its file. Linking to the definition in the other file is handled when the object files are linked. Calling a function that is defined in the same file is relatively simple. The definition or a declaration of it must be above the call. Argument passingAn argument is passed to a function by value which means that a called function receives a copy of the argument and cannot alter the argument variable. For a function to alter the value of a variable, the caller passes the variable's address (a pointer) which simulates what other languages provide as by reference. The called function can modify the variable by dereferencing the passed address. In the following code, the address of void incInt(int *y) { (*y)++; }
int main(void)
{
int x = 7;
incInt(&x);
return 0;
}
The following code demonstrates a more advanced use of pointers – passing a pointer to a pointer. An int pointer named #include <stdio.h>
#include <stdlib.h>
void allocate_array(int ** const a_p, const int count) {
*a_p = malloc(sizeof(int) * count);
}
int main(void) {
int *a;
allocate_array(&a, 42);
free(a);
return 0;
}
Array passingFunction parameters of array type may at first glance appear to be an exception to the pass-by-value rule as demonstrated by the following program that prints 123; not 1: #include <stdio.h>
void setArray(int array[], int index)
{
array[index] = 123;
}
int main(void)
{
int a[1] = {1};
setArray(a, 0);
printf("a[0]=%d\n", a[0]);
return 0;
}
However, there is a different reason for this behavior. An array parameter is treated as a pointer. The following prototype is equivalent to the function prototype above: void setArray(int *array, int index);
At the same time, rules for the use of arrays in expressions cause the value of Since C99, the programmer can specify that a function takes an array of a certain size by using the keyword AttributesAdded in C23 and originating from C++11, C supports attribute specifier sequences.[9] Attributes can be applied to any symbol that supports them, including functions and variables, and any symbol marked with an attribute will be specifically treated by the compiler as necessary. These can be thought of as similar to Java annotations for providing additional information to the compiler, however they differ in that attributes in C are not metadata that is meant to be accessed using reflection. Furthermore, one cannot create custom attributes in C, unlike in Java where one may define custom annotations in addition to the standard ones. However, C does have implementation/vendor-specific attributes which are non-standard. These typically have a namespace associated with them. For instance, GCC and Clang have attributes under the The syntax of using an attribute on a function is like so: [[nodiscard]]
bool satisfiesProperty(const struct MyStruct* s);
The standard defines the following attributes:
Dynamic memoryC dynamic memory allocation refers to performing manual memory management for dynamic memory allocation in the C programming language via a group of functions in the C standard library, namely malloc, realloc, calloc, aligned_alloc and free.[10][11][12] The C++ programming language includes these functions; however, the operators new and delete provide similar functionality and are recommended by that language's authors.[13] Still, there are several situations in which using See also
Notes
References
External links |
Portal di Ensiklopedia Dunia